﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace FeeCrack
{
    public delegate void ProgressUpdateHandler(double per);

    public class DigitMap
    {
        public event ProgressUpdateHandler ProgressUpdate;
        
        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);

        private string[,] digitCodes=new string[10,10];

        //public string[,] DigitCodes { get { return digitCodes; } }
        private IDictionary<string,Digit> digits = new Dictionary<string,Digit>();
        private IDictionary<string, Digit> decimalPoints = new Dictionary<string, Digit>();
        public IDictionary<string,Digit> Digits
        {
            get
            {
                return digits;
            }
        }

        public  void Load(string file)
        {
            Microsoft.Office.Interop.Excel.Application excelApp = null;

            try
            {
                excelApp = new Microsoft.Office.Interop.Excel.Application();
                Microsoft.Office.Interop.Excel.Worksheet sheet = null;

                excelApp.Workbooks.Open(file);

                sheet = excelApp.Worksheets["数字符号"];

                //Microsoft.Office.Interop.Excel.Range range = sheet.Range["B2", "H11"];

                int row=2;
                int col=2;

                for(row=2;row<=11;row++)
                {
                    for (col = 2; col <= 11; col++)
                    {
                        object v = sheet.Cells[row, col].Value;

                        string str = v == null ? null : v.ToString();
                        digitCodes[row - 2, col - 2] = sheet.Cells[row, col].Value;

                        if (!string.IsNullOrEmpty(str))
                        {
                            Digit d = new Digit(str, row, col);
                            digits.Add(d.Code,d);
                        }
                    }
                }

                Microsoft.Office.Interop.Excel.Worksheet sheet2 = null;

                sheet2 = excelApp.Worksheets["小数点符号"];

                for (row = 1; row <= 6; row++)
                {
                    object v = sheet2.Cells[row, 2].Value;
                    string str = v == null ? null : v.ToString().Trim();

                    if (!string.IsNullOrEmpty(str))
                    {
                        Digit p = new Digit(str, row);
                        decimalPoints.Add(p.Code, p);
                    }
                }

                //IList<string> ss = range.Cast<string>().ToList<string>();

                excelApp.Workbooks.Close();
                excelApp.Quit();

            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                KillExcel(excelApp);
            }
        }

        public static void KillExcel(Microsoft.Office.Interop.Excel.Application excel)
        {
            IntPtr t = new IntPtr(excel.Hwnd); //得到这个句柄，具体作用是得到这块内存入口 
            int k = 0;
            GetWindowThreadProcessId(t, out k); //得到本进程唯一标志k 
            System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k); //得到对进程k的引用 
            p.Kill(); //关闭进程k 
        }

        public void Crack(string file)
        {
            Microsoft.Office.Interop.Excel.Application excelApp = null;

            

            try
            {
                excelApp = new Microsoft.Office.Interop.Excel.Application();

                excelApp.Workbooks.Open(file);

                Microsoft.Office.Interop.Excel.Worksheet sheet = null;
                sheet = excelApp.Sheets[1];

                int feeCol = FindFeeColumn(sheet);

                if (feeCol == -1)
                {
                    throw new Exception("没有Fee列");
                }

                int maxRow = sheet.UsedRange.Rows.Count;

                for (int row = 2; row <= maxRow; row++)
                {
                    Microsoft.Office.Interop.Excel.Range cell = sheet.Cells[row, feeCol];

                    object v=cell.Value;

                    if(v!=null)
                    {
                        string code=v.ToString().Trim();
                        Tuple<string, bool> result = Decryption(code);

                        Microsoft.Office.Interop.Excel.Range cell2 = sheet.Cells[row, feeCol + 1];

                        if (result.Item2)
                        {
                            cell2.Value = double.Parse(result.Item1);
                        }
                        else
                        {
                            cell2.Value = result.Item1;
                        }

                    }

                    if (ProgressUpdate != null)
                    {
                        double p = ((double)row / maxRow) * 100;

                        ProgressUpdate(p);
                    }

                }

                excelApp.Visible = true;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        private int FindFeeColumn(Microsoft.Office.Interop.Excel.Worksheet sheet)
        {
            int col = -1;

            int maxCol = sheet.UsedRange.Columns.Count;

            for (int i = 1; i <= maxCol; i++)
            {
                object v = sheet.Cells[1, i].Value;

                if (v != null)
                {
                    string name = v.ToString().Trim();

                    if (name.ToUpper() == "FEE")
                    {
                        col = i;
                        break;
                    }
                }
            }

            return col;
        }

        public Tuple<string, bool> Decryption(string code)
        {
            string number = string.Empty;
            Tuple<string, bool> result = null;
            int x=0;
            int position = 1;
            bool success = true;

            int decimalPosition = 0;

            int max = code.Length;

            while (x<max)
            {
                string key= code.Substring(x, 2);

                if (digits.ContainsKey(key) && digits[key].Code == key && digits[key].Position == position)
                {
                    int n = digits[key].Number;
                    number += n.ToString();

                }
                else if (decimalPoints.ContainsKey(key) && decimalPoints[key].Code == key && decimalPoints[key].Position == position)
                {
                    number += ".";
                    decimalPosition = position;
                }
                else if (position == 1 && key == "17")
                {
                    number = "0.";
                    decimalPosition = 1;
                }
                else if (position > decimalPosition)//!decimalPoints.ContainsKey(key) && x == max - 2
                {

                    number += "0";
                }
                else
                {
                    number = "未找到Key:" + key;
                    success = false;
                    break;
                }
                x += 2;
                position++;
            }


            result = new Tuple<string, bool>(number, success);

            return result;
        }
    }
}
